self.onmessage = async ({ data }) => {
  const input: number[] = data.input
  let idx = 0

  const mem = new WebAssembly.Memory({ initial: 0 })
  mem.grow(data.mem)

  const inst = await WebAssembly.instantiate(data.mod as WebAssembly.Memory, {
    js: {
      mem,
      putchar(ch: number) {
        self.postMessage({ type: 'out', code: ch & 255 })
      },
      getchar() {
        if (idx >= input.length) {
          self.postMessage({ type: 'err', msg: 'Input Overflow' })
          self.close()
        }
        return input[idx++]
      }
    }
  })

  try {
    ; (inst.exports.run as (pos: number) => void)(data.pos)
    self.postMessage({ type: 'end' })
  } catch (e) {
    self.postMessage({ type: 'err', msg: (e as Error).message })
  }
  self.close()
}